using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

//**********************************************
// Cylinder, derives from Base Primitive
//**********************************************
namespace MechaShark
{
    public class Cylinder : BasePrimitive //inherits from BasePrimitive
    {
        //-------------Methods-------------
        //constructor(overloaded)
        public Cylinder(GraphicsDevice graphicsDevice) //default ( height = 1, diameter = 1, tessellation = 32 )
            : this(graphicsDevice, 1, 1, 32)
        {
        }

        public Cylinder(GraphicsDevice graphicsDevice, float height, float diameter, int tessellation)//cylinder of specified size, tessellation
         {
             if (tessellation < 3) //minimum tessellation, tessellation is the space between rendered parts
                 throw new ArgumentOutOfRangeException("tessellation");
             height /= 2;
             float radius = diameter / 2;

             for (int i = 0; i < tessellation; i++) //create the cylinder
             {
                 Vector3 normal = GetCircleVector(i, tessellation);
                 AddVertex(normal * radius + Vector3.Up * height, normal);
                 AddVertex(normal * radius + Vector3.Down * height, normal);

                 AddIndex(i * 2);
                 AddIndex(i * 2 + 1);
                 AddIndex((i * 2 + 2) % (tessellation * 2));

                 AddIndex(i * 2 + 1);
                 AddIndex((i * 2 + 3) % (tessellation * 2));
                 AddIndex((i * 2 + 2) % (tessellation * 2));
             }

             //create our cylinder caps
             CreateCap(tessellation, height, radius, Vector3.Up);
             CreateCap(tessellation, height, radius, Vector3.Down);

             InitializePrimitive(graphicsDevice); //Base Primitive initialization

         }
        //method to close ends of the cylinder
        void CreateCap(int tessellation, float height, float radius, Vector3 normal)
         {
             // Create cap indices.
             for (int i = 0; i < tessellation - 2; i++)
             {
                 if (normal.Y > 0)
                 {
                     AddIndex(CurrentVertex);
                     AddIndex(CurrentVertex + (i + 1) % tessellation);
                     AddIndex(CurrentVertex + (i + 2) % tessellation);
                 }
                 else
                 {
                     AddIndex(CurrentVertex);
                     AddIndex(CurrentVertex + (i + 2) % tessellation);
                     AddIndex(CurrentVertex + (i + 1) % tessellation);
                 }
             }

             // Create cap vertices.
             for (int i = 0; i < tessellation; i++)
             {
                 Vector3 position = GetCircleVector(i, tessellation) * radius +
                                    normal * height;

                 AddVertex(position, normal);
             }
         }
        //method to compute a point on a circle
        static Vector3 GetCircleVector(int i, int tessellation)
        {
            float angle = i * MathHelper.TwoPi / tessellation;

            float dx = (float)Math.Cos(angle);
            float dz = (float)Math.Sin(angle);

            return new Vector3(dx, 0, dz);
        }
    }
}
